package com.baidu.iit.pxp.util;

import com.baidu.iit.pvm.PvmProcessDefinition;
import com.baidu.iit.pvm.PvmScope;
import com.baidu.iit.pvm.delegate.ActivityBehavior;
import com.baidu.iit.pvm.delegate.ActivityExecution;
import com.baidu.iit.pvm.process.ActivityImpl;
import com.baidu.iit.pxp.entity.ExecutionEntity;

/**
 * User: huangweili
 * Date: 14-4-28
 * Time: 下午3:55
 */
public class ScopeUtil {


    public static ActivityExecution findScopeExecution(ActivityExecution execution) {

        while(!execution.isScope()) {
            execution = execution.getParent();
        }

        if(execution.isConcurrent()) {
            execution = execution.getParent();
        }

        return execution;

    }



    public static ExecutionEntity findScopeExecutionForScope(ExecutionEntity execution, PvmScope scopeActivity) {

        if (scopeActivity instanceof PvmProcessDefinition) {
            return execution.getProcessInstance();

        } else {

            ActivityImpl currentActivity = execution.getActivity();
            ExecutionEntity candiadateExecution = null;
            ExecutionEntity originalExecution = execution;

            while (execution != null) {
                currentActivity = execution.getActivity();
                if (scopeActivity.getActivities().contains(currentActivity)
                        || scopeActivity.equals(currentActivity)) {

                    candiadateExecution = execution;
                } else if (currentActivity!= null
                        && currentActivity.contains((ActivityImpl)scopeActivity)) {
                    break;
                }

                execution = execution.getParent();
            }

            if(originalExecution == candiadateExecution
                    && originalExecution.getActivity().isScope()
                    && !originalExecution.getActivity().equals(scopeActivity)) {
                candiadateExecution = originalExecution.getParent();
            }

            return candiadateExecution;
        }
    }

    public static ActivityImpl findInParentScopesByBehaviorType(ActivityImpl activity, Class<? extends ActivityBehavior> behaviorType) {
        while (activity != null) {
            for (ActivityImpl childActivity : activity.getActivities()) {
                if(behaviorType.isAssignableFrom(childActivity.getActivityBehavior().getClass())) {
                    return childActivity;
                }
            }
            activity = activity.getParentActivity();
        }
        return null;
    }

   /*
    public static void throwCompensationEvent(List<CompensateEventSubscriptionEntity> eventSubscriptions, ActivityExecution execution, boolean async) {


        for (EventSubscriptionEntity eventSubscription : eventSubscriptions) {
            ExecutionEntity compensatingExecution = null;
            // check whether compensating execution is already created
            // (which is the case when compensating an embedded subprocess,
            // where the compensating execution is created when leaving the subprocess
            // and holds snapshot data).
            if(eventSubscription.getConfiguration() !=null) {
                compensatingExecution = Context.getCommandContext()
                        .getExecutionEntityManager()
                        .findExecutionById(eventSubscription.getConfiguration());

                compensatingExecution.setParent((InterpretableExecution) execution);
                compensatingExecution.setEventScope(false);
            } else {
                compensatingExecution = (ExecutionEntity) execution.createExecution();
                eventSubscription.setConfiguration(compensatingExecution.getId());
            }
            compensatingExecution.setConcurrent(true);
        }

        Collections.sort(eventSubscriptions, new Comparator<EventSubscriptionEntity>() {
            public int compare(EventSubscriptionEntity o1, EventSubscriptionEntity o2) {
                return o2.getCreated().compareTo(o1.getCreated());
            }
        });

        for (CompensateEventSubscriptionEntity compensateEventSubscriptionEntity : eventSubscriptions) {
            compensateEventSubscriptionEntity.eventReceived(null, async);
        }
    }


    public static void createEventScopeExecution(ExecutionEntity execution) {

        ExecutionEntity eventScope = ScopeUtil.findScopeExecutionForScope(execution, execution.getActivity().getParent());

        List<CompensateEventSubscriptionEntity> eventSubscriptions = execution.getCompensateEventSubscriptions();

        if(eventSubscriptions.size() > 0) {

            ExecutionEntity eventScopeExecution = eventScope.createExecution();
            eventScopeExecution.setActive(false);
            eventScopeExecution.setConcurrent(false);
            eventScopeExecution.setEventScope(true);
            eventScopeExecution.setActivity((ActivityImpl) execution.getActivity());

            execution.setConcurrent(false);

            Map<String, Object> variables = execution.getVariablesLocal();
            for (Map.Entry<String, Object> variable : variables.entrySet()) {
                eventScopeExecution.setVariableLocal(variable.getKey(), variable.getValue());
            }

            for (CompensateEventSubscriptionEntity eventSubscriptionEntity : eventSubscriptions) {
                eventSubscriptionEntity = eventSubscriptionEntity.moveUnder(eventScopeExecution);
            }

            CompensateEventSubscriptionEntity eventSubscription = CompensateEventSubscriptionEntity.createAndInsert(eventScope);
            eventSubscription.setActivity(execution.getActivity());
            eventSubscription.setConfiguration(eventScopeExecution.getId());

        }
    }  */

}
